<template>
  <div>
    <el-row>
      <el-col :span="6">
        <div class="friends-list">
          <div class="friends-list-nav">
            <el-row>
              <el-col :span="8" class="friends-list-nav-item" @click="switchNav(1)">
                <el-button link>好友</el-button>
              </el-col>
              <el-col :span="8" class="friends-list-nav-item" @click="switchNav(2)">
                <el-button link>群组</el-button>
              </el-col>
              <el-col :span="8" class="friends-list-nav-item" @click="switchNav(3)">
                <el-button link>好友请求</el-button>
              </el-col>
            </el-row>
          </div>
          <div v-show="navIndex==1">
            <div class="friends-item" v-for="(item,index) in friendsList" :key="item.uid"
                 @click="clickFriends(item.uid)">
              {{ item.nickname }}
              <br/>
              {{ item.email }}
            </div>
          </div>
          <div v-show="navIndex==2">
            <p v-for="(item,index) in groupList" :key="item.pId" @click="clickGroupMessage(item.pId)">
              项目：{{ item.name }}
            </p>
          </div>
          <div v-show="navIndex==3">
            <div class="input-with-button">
              <el-input
                  v-model="addFriendsEmailInput"
                  placeholder="请输入朋友的邮箱地址"
              ></el-input>
              <el-button type="primary" size="small" @click="addFriendsOps(addFriendsEmailInput)">
                添加
              </el-button>
            </div>
            <div class="friendsOpsList" v-for="(item,index) in friendsOpsList" :key="item.uid">
              <el-row>
                <el-col :span="20">
                  {{ item.nickname }}
                  <br/>
                  {{ item.email }}
                </el-col>
                <el-col :span="4">
                  <el-button type="primary" size="small" @click="agreeFriendsOps(item.uid)">
                    同意
                  </el-button>
                  <br/>
                  <el-button type="danger" size="small" @click="rejectFriendsOps(item.uid)">
                    拒绝
                  </el-button>
                </el-col>
              </el-row>
              <el-divider/>
            </div>
          </div>
        </div>

      </el-col>
      <el-col :span="18">
        <div class="talk" v-if="messageType == 'SIGNAL'">
          <div class="talk-header">
                        <span class="talk-header-nickname">
                            {{ currentTalk.nickname }}
                        </span>
            <br/>
            <span class="talk-header-email">
                            {{ currentTalk.email }}
                        </span>
          </div>
          <div class="talk-content">
            <el-scrollbar ref="scrollbar" max-height="400px">
              <p @click="nextPage">历史纪录</p>
              <div ref="innerRef">
                <Message v-for="(item,index) in singleMessageList"
                         :key="index"
                         :message="item"
                         :current-talk="currentTalk"
                />
              </div>
            </el-scrollbar>
          </div>
          <div class="talk-footer">
            <el-row>
              <el-col :span="22">
                <el-input type="textarea" :rows="2" v-model="inputContent"></el-input>
              </el-col>
              <el-col :span="2" @click="sendMessage">
                发送
              </el-col>
            </el-row>
          </div>
        </div>
        <div class="talk" v-if="messageType == 'GROUP'">
          <div class="talk-header">
                        <span class="talk-header-nickname">
                            项目：{{ currentlyGroup.name }}
                        </span>
          </div>
          <div class="talk-content">
            <el-scrollbar ref="scrollbar" max-height="400px">
              <p @click="">历史纪录</p>
              <div ref="innerRef">
                <GroupMessage v-for="(item,index) in groupMessageList"
                              :key="index"
                              :message="item"
                />
              </div>
            </el-scrollbar>
          </div>
          <div class="talk-footer">
            <el-row>
              <el-col :span="22">
                <el-input type="textarea" :rows="2" v-model="inputContent"></el-input>
              </el-col>
              <el-col :span="2" @click="sendMessage">
                发送
              </el-col>
            </el-row>
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<script lang="ts" setup>
import io from "socket.io-client";
import {nextTick, onBeforeMount, reactive, ref} from "vue";
import Message from "@/components/IM/Message.vue";
import {
  addFriendsAPI,
  agreeFriendsRequestAPI,
  getFriendsList,
  getFriendsRequestAPI,
  rejectFriendsRequestAPI
} from "@/api/IM/FriendsAPI";
import type {ProjectInterface, ResponseInterface, UserInterface} from "@/type/models";
import {getHistoryMessageAPI, sendSignalMessageAPI} from "@/api/IM/MessageAPI";
import type {GroupMessageInterface, MessageInterface} from "@/type/IMModels";
import {ElMessage} from "element-plus";
import {getProjectListAPI, getTeamMemberAPI} from "@/api/project/ProjectAPI";
import {getGroupMessageHistoryAPI, sendGroupMessageAPI} from "@/api/IM/GroupMessageAPI";
import GroupMessage from "@/components/IM/GroupMessage.vue";

const TOKEN: string = localStorage.getItem("token") as string;

//---begin websocket
// 创建并返回一个与服务器建立WebSocket连接的实例
const ws = getSocket(TOKEN);

/**
 * 获取WebSocket连接实例。
 * @param token {string} 用于建立连接的令牌。
 * @returns 返回一个初始化好的WebSocket连接实例。
 */
function getSocket(token: string) {
  // 使用Socket.IO库来创建WebSocket连接，配置连接参数
  const ws = io('http://localhost:8088', {
    transports: ['websocket'], // 指定使用WebSocket作为传输协议
    autoConnect: true, // 连接时自动尝试连接
    reconnection: true, // 连接断开后自动尝试重新连接
    reconnectionAttempts: 3, // 限制重新连接尝试次数
    reconnectionDelay: 1000, // 重新连接尝试的延迟时间
    query: {token: token}, // 向服务器传递的附加查询参数
  })
  ws.on("message", (data) => {
    console.log("收到信息", data)
    acceptSingleMessage(data)
  })
  ws.on("groupMessage", (data) => {
    console.log("收到信息", data)
    acceptGroupMessage(data)
  })
  return ws
}

function acceptSingleMessage(data: MessageInterface) {
  if (currentTalk.uid == data.fromUid) {
    data.time = new Date(data.time)
    singleMessageList.push(data)
    setScrollToBottom()
  }
}
function acceptGroupMessage(data: GroupMessageInterface) {
  if (currentlyGroup.value.pId == data.groupId) {
    data.time = new Date(data.time)
    groupMessageList.push(data)
    setScrollToBottom()
  }
}
//---end websocket
//---start friends
let navIndex = ref(1);
const friendsList: Array<UserInterface> = reactive([]);

function switchNav(index: number) {
  navIndex.value = index
  switch (index) {
    case 1: {
      break
    }
    case 2: {
      getGroupList()
      break
    }
    case 3: {
      getFriendsRequestOpsList(TOKEN)
      break
    }
  }
}

function clickFriends(uid: string) {
  for (let i = 0; i < friendsList.length; i++) {
    if (friendsList[i].uid === uid) {
      Object.assign(currentTalk, friendsList[i])
    }
  }
  //清空singleMessageList
  messagePage.value = 1
  singleMessageList.splice(0, singleMessageList.length);
  getSingleMessageHistory(currentTalk)
  messageType.value = "SIGNAL"
}

//---end friends
//---start talk
const inputContent = ref("");
let currentTalk = reactive<UserInterface>({email: "", nickname: "", uid: ""});
const singleMessageList = reactive<Array<MessageInterface>>([]);
let messageType = ref<"SIGNAL" | "GROUP">("SIGNAL")
let messagePage = ref<number>(1)
const scrollbar = ref() // 滚动条实例
const innerRef = ref() // 计数器内部实例
let scrollNumber = ref(0)

async function getSingleMessageHistory(currentTalk: UserInterface) {
  const r: ResponseInterface = await getHistoryMessageAPI(TOKEN, currentTalk.uid, messagePage.value, 5)
  if (r.code == 200) {
    singleMessageList.push(...r.data)
  }
  await setScrollToBottom()
  console.log(singleMessageList)
}

/**
 * 控制滚动条滚动到容器的底部
 */
async function setScrollToBottom() {
  // 注意：需要通过 nextTick 以等待 DOM 更新完成
  await nextTick()
  const max = innerRef.value!.clientHeight
  scrollbar.value!.setScrollTop(max)
}

async function nextPage() {
  messagePage.value++
  await getSingleMessageHistory(currentTalk)
}

async function sendMessage() {
  if (!beforeSendMessage()) {
    return;
  }
  if (messageType.value === "signal".toUpperCase()) {
    const r: ResponseInterface = await sendSignalMessageAPI(inputContent.value, currentTalk.uid, TOKEN)
    if (r.code == 200) {
      singleMessageList.push(r.data)
    }
  }
  if (messageType.value === "group".toUpperCase()) {
    const r: ResponseInterface = await sendGroupMessageAPI(inputContent.value, currentlyGroup.value.pId, TOKEN)
    if (r.code == 200) {
      groupMessageList.push(r.data)
    }
  }
  afterSendMessage()
}

function beforeSendMessage(): boolean {
  if (currentTalk.uid.length == 0 && messageType.value === "signal".toUpperCase()) {
    ElMessage.warning("请选择聊天对象")
    return false
  }
  if (currentlyGroup.value.pId.length == 0 && messageType.value === "group".toUpperCase()) {
    ElMessage.warning("请选择聊天对象")
    return false
  }
  if (inputContent.value.length == 0) {
    ElMessage.warning("请输入内容")
    return false
  }
  return true;
}

function afterSendMessage() {
  inputContent.value = ""
  setScrollToBottom()
}

//---end talk

//---friends request
const friendsOpsList = reactive<Array<UserInterface>>([])
let addFriendsEmailInput = ref<string>("")

async function addFriendsOps(email: string) {
  const r: ResponseInterface = await addFriendsAPI(TOKEN, email)
  if (r.code == 200) {
    ElMessage.success("已发送好友请求")
    addFriendsEmailInput.value = ""
  }
}

async function getFriendsRequestOpsList(token: string) {
  const r: ResponseInterface = await getFriendsRequestAPI(token)
  if (r.code == 200) {
    friendsOpsList.splice(0, friendsOpsList.length)
    friendsOpsList.push(...r.data)
  }
}

async function agreeFriendsOps(friendsUid: string) {
  const r: ResponseInterface = await agreeFriendsRequestAPI(TOKEN, friendsUid)
  if (r.code == 200) {
    ElMessage.success("操作成功")
    deleteSomeOneByOpsList(friendsUid)
    await getFriendsList(TOKEN)
  }
}

async function rejectFriendsOps(friendsUid: string) {
  const r: ResponseInterface = await rejectFriendsRequestAPI(TOKEN, friendsUid)
  if (r.code == 200) {
    ElMessage.success("操作成功")
    deleteSomeOneByOpsList(friendsUid)
  }
}

function deleteSomeOneByOpsList(uid: string) {
  for (let i = 0; i < friendsOpsList.length; i++) {
    if (friendsOpsList[i].uid === uid) {
      friendsOpsList.splice(i, 1)
    }
  }
}

//---end friends request
//---group message
const groupList = reactive<Array<ProjectInterface>>([])
const groupMessageList = reactive<Array<GroupMessageInterface>>([])
let currentlyGroup = ref<ProjectInterface>({created: "", name: "", owner: 0, pId: ""})

async function getGroupList() {
  const r: ResponseInterface = await getProjectListAPI(TOKEN, 1)
  if (r.code == 200) {
    groupList.splice(0, groupList.length)
    groupList.push(...r.data)
  }
}

async function getGroupMessageHistory(pid: string, page: number) {
  const r: ResponseInterface = await getGroupMessageHistoryAPI(TOKEN, pid, page, 5)
  if (r.code == 200) {
    groupMessageList.push(...r.data)
  }
}

async function clickGroupMessage(pid: string) {
  messageType.value = "GROUP"
  messagePage.value = 1
  groupMessageList.splice(0, groupMessageList.length)
  currentlyGroup.value = groupList.find(item => item.pId === pid)
  await getGroupMessageHistory(pid, messagePage.value)
  await getTeamMember(pid)
}

async function getTeamMember(pid: string) {
  const r: ResponseInterface = await getTeamMemberAPI(TOKEN, pid)
  if (r.code == 200) {
    localStorage.setItem("teamMember", JSON.stringify(r.data))
  }
}

//---end group message
onBeforeMount(async () => {
  Object.assign(friendsList, (await getFriendsList(TOKEN)).data)
  await getFriendsRequestOpsList(TOKEN)
})
</script>
<style scoped>
.friends-list {
  border: black solid 1px;
  height: 500px;
  background: skyblue;
}

.friends-list-nav {
  height: 40px;
  line-height: 40px;
}

.friends-list-nav-item {
  color: black;
  text-align: center;
  border: white solid 1px;
}

.talk {
  height: 500px;
  background: lightgreen;
}

.talk-header {
  height: 10%;
  background: orange;
  font-family: "HarmonyOS Sans SC", serif;
}

.talk-content {
  height: 70%;
}

.talk-footer {
  height: 15%;
  background: blueviolet;
}

.talk-header-nickname {
  font-size: 20px;
}

.talk-header-email {
  font-size: 15px;
}

.friends-item {
  margin-bottom: 3px;
  padding-left: 3px;
  font-family: "HarmonyOS Sans SC", serif;
}

.input-with-button {
  display: flex;
  align-items: center;
  gap: 0px; /* 调整输入框与按钮之间的间距 */
}

.friendsOpsList {
  margin-top: 10px;
}
</style>